package com.bootcamp.mall.service.goods;

import com.bootcamp.mall.dao.GoodsDao;
import com.bootcamp.mall.dao.UserDao;
import com.bootcamp.mall.model.Goods;
import com.bootcamp.mall.model.GoodsType;
import com.bootcamp.mall.model.Spec;
import com.bootcamp.mall.model.User;
import com.bootcamp.mall.model.bo.goods.GoodsBO;
import com.bootcamp.mall.model.bo.goods.MsgBO;
import com.bootcamp.mall.model.vo.goods.*;
import com.bootcamp.mall.utils.MyBatisUtil;
import com.bootcamp.mall.utils.StringUtil;
import org.apache.ibatis.session.SqlSession;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * @program: mall
 * @description:
 * @author: Keyu Li
 * @create: 2021-11-10 14:58
 **/

public class GoodsServiceImpl implements GoodsService {
    @Override
    public List<GoodsType> getTypes() {
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        List<GoodsType> goodsTypes = mapper.selectAllTypes();
        // close
        sqlsession.close();
        return goodsTypes;
    }

    @Override
    public List<GoodsVO> getGoodsByType(Integer typeId) {
        // 将 typeId 包装为 Goods 对象
        Goods goods = new Goods();
        goods.setTypeId(typeId);
        // sqlsession,mapper,method,close四联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        // 不再进行繁琐的类型转换，直接返回vo
        List<GoodsVO> goodsByTypeVOS = mapper.selectGoods(goods);
        // close
        sqlsession.close();
        return goodsByTypeVOS;
    }


    @Override
    public List<GoodsVO> searchGoods(Goods goods) {
        // 调用dao中的搜索方法
        // sqlsession,mapper,method,close四联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        // 不再进行繁琐的类型转换，直接返回vo
        List<GoodsVO> goodsByTypeVOS = mapper.selectGoods(goods);
        // close
        sqlsession.close();
        return goodsByTypeVOS;
    }


    @Override
    public boolean addTypes(GoodsType goodsType) {
        // sqlsession,mapper,method,close,trycatch commit/roolback六联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        try {
            mapper.insertTypes(goodsType);
            sqlsession.commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return false;
        } finally {
            sqlsession.close();
        }
    }

    @Override
    public Integer deleteType(Integer typeId) {
        int newTypeId = 1;
        // sqlsession,mapper,method,close,trycatch commit/rollback六联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        try {
            // 此时可以确保 typeId 是合法的，且不是默认的 未分类 类目，现在将该类目下所有商品id转移到未分类类目
            // 删除类目表 Type
            mapper.deleteTypeById(typeId);
            // 更新商品表 Goods
            mapper.updateGoodsTypeId(newTypeId, typeId);
            sqlsession.commit();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return 1;
        } finally {
            sqlsession.close();
        }
    }

    @Override
    public Integer addGoods(GoodsBO goodsBO) {
        List<Spec> specList = goodsBO.getSpecList();
        // Goods
        BigDecimal goodsPrice = specList.get(0).getUnitPrice();
        Integer goodsStock = 0;
        for (Spec spec : specList) {
            BigDecimal price = spec.getUnitPrice();
            Integer stockNum = spec.getStockNum();
            // 对stockNum和price进行校验，如果 <0 则返回错误
            if (price.compareTo(new BigDecimal("0")) < 0 || stockNum < 0) {
                return -1;
            }
            // 获取最小的price，以及stockNum的总和
            goodsPrice = goodsPrice.min(price);
            goodsStock += stockNum;
        }
        // set 赋值给goods表
        Goods goods = new Goods();
        goods.setName(goodsBO.getName());
        // database存储的 img 不包含 主机+端口！
        goods.setImage(goodsBO.getImg());
        goods.setTypeId(goodsBO.getTypeId());
        goods.setDescription(goodsBO.getDesc());
        goods.setStockNum(goodsStock);
        goods.setPrice(goodsPrice);

        // sqlsession,mapper,method,close,trycatch commit/rollback七联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        try {
            // 添加Goods表返回id
            mapper.insertGoods(goods);
            // 补全Spec，添加Spec表
            Integer goodsId = goods.getId();
            for (Spec s : specList) {
                s.setGoodsId(goodsId);
            }
            mapper.insertSpec(specList);
            sqlsession.commit();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return 1;
        } finally {
            sqlsession.close();
        }
    }

    @Override
    public GetGoodsInfoVO getGoodsInfo(int id) {
        // sqlsession,mapper,method,close四联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        // 先查询goods表
        GoodsVO goodsVO = mapper.selectGoodsById(id);
        // 查询spec表
        List<Spec> specVOS = mapper.selectSpecListByGoodsId(id);
        // 合并对象
        GetGoodsInfoVO getGoodsInfoVO = new GetGoodsInfoVO();
        getGoodsInfoVO.setGoods(goodsVO);
        getGoodsInfoVO.setSpecs(specVOS);
        // close
        sqlsession.close();
        return getGoodsInfoVO;
    }

    @Override
    public GoodsVO getGoodsInfoFront(Integer id) {
        // sqlsession,mapper,method,close四联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        // 先查询goods表
        GoodsVO goodsVO = mapper.selectGoodsById(id);
        // 查询spec表
        List<Spec> specVOS = mapper.selectSpecListByGoodsId(id);
        // 合并对象
        goodsVO.setSpecs(specVOS);
        // close
        sqlsession.close();
        return goodsVO;
    }

    @Override
    public List<GoodsMsgVO> getGoodsMsg(Integer goodsId) {
        // sql四连
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        // 联合查询 message表 和 user表
        List<GoodsMsgVO> goodsMsgVOS = mapper.selectMsgAndAskerByGoodsId(goodsId);
        // close
        sqlsession.close();
        return goodsMsgVOS;
    }

    @Override
    public Integer addGoodsMsg(MsgBO msgBO) {
        // msgBO 中会自动添加当前时间

        // sqlsession,mapper,method,close,trycatch commit/rollback六联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        UserDao mapperUser = sqlsession.getMapper(UserDao.class);
        try {
            // 先查询user表获得 userid
            Integer userId = mapperUser.selectIdByNickname(msgBO.getToken());
            msgBO.setUserId(userId);
            msgBO.setState(1);
            int affectRows = mapper.insertMsg(msgBO);
            System.out.println(affectRows);
            sqlsession.commit();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return -1;
        } finally {
            sqlsession.close();
        }

    }

    @Override
    public GetCommentVO getGoodsComment(Integer goodsId) {
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        // 获取 CommentOfGetVO list
        List<CommentOfGetVO> commentOfGetVOS = mapper.selectCommentByGoodsId(goodsId);
        // close
        sqlsession.close();
        // 计算 rate

        //TODO: 3星及以下为差评，4-5星为好评
        int totalScore = 0;
        int num = commentOfGetVOS.size();
        for (CommentOfGetVO comment : commentOfGetVOS) {
            totalScore += comment.getScore();
        }
        // 防止发生除0错误
        Double rate = num == 0 ? 0 : totalScore * 1.0 / num;
        // 封装为 GetCommentVO
        GetCommentVO getCommentVO = new GetCommentVO();
        getCommentVO.setCommentList(commentOfGetVOS);
        getCommentVO.setRate(rate);
        return getCommentVO;
    }

    @Override
    public boolean deleteGoods(Integer id) {
        // sqlsession,mapper,method,close,trycatch commit/rollback六联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        try {
            mapper.deleteGoodsById(id);
            mapper.deleteSpecByGoodsId(id);
            sqlsession.commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return false;
        } finally {
            sqlsession.close();
        }
    }

    @Override
    public Integer addSpec(Spec addSpecBO) {
        return null;
    }

    @Override
    public Integer deleteSpec(Spec deleteSpecBO) {
        // sql删除七连
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        try {
            Integer affectRows = mapper.deleteSpecByGoodsIdAndName(deleteSpecBO);
            System.out.println(affectRows+": 为1表示删除成功，为0表示没有此spec");
            sqlsession.commit();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return 500;
        } finally {
            sqlsession.close();
        }
    }

    @Override
    public Integer updateGoods(GoodsBO goodsBO) {
        // 先遍历spec列表，确保没有同名，同时搜索最大值，同时判断update和insert的spec
        List<Spec> insertSpecs = new ArrayList<>();
        List<Spec> updateSpecs = new ArrayList<>();
        HashSet<String> specNames = new HashSet<>();
        Integer goodsVOId = goodsBO.getId();
        List<Spec> specList = goodsBO.getSpecList();
        BigDecimal goodsPrice = specList.get(0).getUnitPrice();
        Integer goodsStock = 0;
        for (Spec spec : specList) {
            BigDecimal unitPrice = spec.getUnitPrice();
            Integer stockNum = spec.getStockNum();
            String specName = spec.getSpecName();
            Integer id = spec.getId();
            Integer goodsId = spec.getGoodsId();
            // 判断 goodsPrice 和 stockNum 合法性：不为负数
            if (goodsPrice.compareTo(new BigDecimal("0")) < 0 || stockNum < 0) {
                return -1;
            }
            // 判断 specName 合法性：不重复
            if (specNames.contains(specName)) {
                return 1;
            } else {
                specNames.add(specName);
            }
            // 判断是更新还是插入
            if (id == null && goodsId == null) {
                return 500;
            } else if (id != null) {
                // 此时goodsId为null，赋值
                spec.setGoodsId(goodsVOId);
                updateSpecs.add(spec);
            } else if (goodsId.equals(goodsVOId)) {
                insertSpecs.add(spec);
            } else {
                return 500;
            }
            // 获取goods的最小价格与库存总数
            goodsPrice = goodsPrice.min(unitPrice);
            goodsStock += stockNum;
        }
        // 首先进行goods表更新操作,获取goods对象
        Goods goods = new Goods();
        goods.setId(goodsBO.getId());
        goods.setName(goodsBO.getName());
        goods.setImage(goodsBO.getImg());
        goods.setTypeId(goodsBO.getTypeId());
        goods.setDescription(goodsBO.getDesc());
        goods.setStockNum(goodsStock);
        goods.setPrice(goodsPrice);

        // sqlsession,mapper,method,close,trycatch commit/rollback七联
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        try {
            mapper.updateGoodsById(goods);
            if (insertSpecs.size() != 0) {
                mapper.insertSpec(insertSpecs);
            }
            // 不管执行多少次update语句，返回都是1，而不是返回的条数
            if (updateSpecs.size() != 0) {
                mapper.updateSpecById(updateSpecs);
            }
            sqlsession.commit();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return 500;
        } finally {
            sqlsession.close();
        }
    }

    @Override
    public List<MsgVO> showMsg(Integer state) {
        // sql查询四连
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        // 查询message表
        List<MsgVO> msgVOS = mapper.selectMsgByState(state);
        // close
        sqlsession.close();
        return msgVOS;
    }

    @Override
    public Integer replyMsg(MsgBO msgBO) {
        // 先判断content是否为空，为空返回 1
        if (StringUtil.isEmpty(msgBO.getContent())) {
            return -1;
        }
        // 把msgBO状态设置为0，表示已经回复
        msgBO.setState(0);
        // sql修改七连
        SqlSession sqlsession = MyBatisUtil.getSqlsession();
        GoodsDao mapper = sqlsession.getMapper(GoodsDao.class);
        try {
            Integer affectRows = mapper.updateMsgByAddReply(msgBO);
            System.out.println(affectRows);
            sqlsession.commit();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            return 500;
        } finally {
            sqlsession.close();
        }

    }

}
